﻿namespace Bundler
{
    using System;
    using System.Collections.Generic;
    using System.IO;
    using System.Text.RegularExpressions;
    using System.Web;

    public class CssMinifyImageEmbed : CssMinify
    {
        #region Constants and Fields

        private const string Format = "url(data:image/{0};base64,{1})";

        private static readonly object SyncRoot = new object();

        private static readonly Regex Url = new Regex(@"url\(['""]?(?<url>[^)]+?\?embed)['""]?\)", RegexOptions.Singleline);

        private static List<string> _fileNames;

        #endregion

        #region Public Methods and Operators

        public override void Process(BundleResponse bundle)
        {
            base.Process(bundle);
            lock (SyncRoot)
            {
                if (_fileNames == null)
                {
                    _fileNames = new List<string>();
                }
            }
            bundle.RequestAction = () => SetHeaders(bundle.Bundle.Options.EnableOptimizations);

            var rootPath = HttpHelper.MapPath("~/");
            if (String.IsNullOrWhiteSpace(rootPath))
                return;

            foreach (Match match in Url.Matches(bundle.Content))
            {
                if (match.Groups.Count < 2)
                    continue;

                var relativePath = match.Groups[1].Value;
                if (string.IsNullOrEmpty(relativePath))
                    continue;

                var fixedRelativePath = relativePath.Substring(0, relativePath.IndexOf("?", StringComparison.OrdinalIgnoreCase)).Replace("/", "\\");

                var absolutePath = Path.Combine(rootPath, fixedRelativePath);
                var mappedPath = Path.GetFullPath((new Uri(absolutePath)).LocalPath);

                var file = new FileInfo(mappedPath);
                if (!file.Exists)
                    continue;

                bundle.Content = bundle.Content.Replace(match.Value, string.Format(Format, file.Extension.Substring(1), Convert.ToBase64String(File.ReadAllBytes(file.FullName))));
                lock (SyncRoot)
                {
                    if (!_fileNames.Contains(file.FullName))
                    {
                        _fileNames.Add(file.FullName);
                    }
                }
            }
        }

        public override void SetHeaders(bool optimize)
        {
            base.SetHeaders(optimize);
            if (!optimize || HttpContext.Current == null)
                return;

            HttpContext.Current.Response.Cache.SetLastModifiedFromFileDependencies();
            lock (SyncRoot)
            {
                if (_fileNames != null)
                {
                    HttpContext.Current.Response.AddFileDependencies(_fileNames.ToArray());
                }
            }
        }

        #endregion
    }
}